package org.xiaog.fastdao;

import org.xiaog.fastdao.util.DataSourceUtil;

import javax.sql.DataSource;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author xiaog
 */
public class FastDaoFactory {

    private static final Map<Class<? extends FastDao>,FastDao> CACHE = new ConcurrentHashMap<>();

    private FastDaoFactory(){}

    public static FastDaoFactory getInstance(DataSource dataSource) {
        DataSourceUtil.init(dataSource);
        return new FastDaoFactory();
    }

    public <T extends FastDao> T getDao(Class<T> daoInterface) {
        T t = (T) CACHE.get(daoInterface);
        if (t == null) {
            DaoProxy daoProxy = new DaoProxy();
            Type[] types = daoInterface.getGenericInterfaces();
            for (Type type : types) {
                String typeName = type.getTypeName();
                int idx = typeName.indexOf("<");
                typeName = idx > -1 ? typeName.substring(0,idx) : typeName;
                if (typeName.equals(FastDao.class.getName())) {
                    ParameterizedType pt = (ParameterizedType) type;
                    daoProxy.setClazz((Class<?>)pt.getActualTypeArguments()[0]);
                    ClassLoader classLoader = daoInterface.getClassLoader();
                    t = (T) Proxy.newProxyInstance(classLoader,new Class[]{daoInterface},daoProxy);
                    CACHE.putIfAbsent(daoInterface,t);
                    break;
                }
            }
        }
        return t;
    }

}
